package com.salton123.soulove.utils

import android.content.UriPermission
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.Build
import android.text.TextUtils
import androidx.documentfile.provider.DocumentFile
import com.blankj.utilcode.util.FileUtils
import com.salton123.app.BaseApplication
import com.salton123.log.XLog
import com.salton123.soulove.app.R
import com.salton123.soulove.sailfish.db.SailfishDatabase
import com.salton123.soulove.sailfish.db.VideoItem
import com.salton123.soulove.sailfish.video.SailfishManager
import com.salton123.util.PreferencesUtils
import kotlinx.coroutines.async
import java.io.File
import java.util.Locale

/**
 * User: wujinsheng1@yy.com
 * Date: 2021/9/4 23:32
 * ModifyTime: 23:32
 * Description:
 */
object Utils {
    const val TAG = "Utils"

    /**
     * 将毫秒数格式化为"##:##"的时间
     * @param milliseconds 毫秒数
     * @return ##:##
     */
    fun formatTime(milliseconds: Long): String {
        if (milliseconds <= 0 || milliseconds >= 24 * 60 * 60 * 1000) {
            return "00:00"
        }
        val totalSeconds = milliseconds / 1000
        val seconds = totalSeconds % 60
        val minutes = totalSeconds / 60 % 60
        val hours = totalSeconds / 3600
        val stringBuilder = StringBuilder()
        val mFormatter = java.util.Formatter(stringBuilder, Locale.getDefault())
        return if (hours > 0) {
            mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
        } else {
            mFormatter.format("%02d:%02d", minutes, seconds).toString()
        }
    }

    fun sortParam(): Pair<Boolean, String> {
        val position = PreferencesUtils.getInt("sort_position", 0)
        return sortParam(position)
    }

    fun sortParam(position: Int): Pair<Boolean, String> {
        var sortType: String
        var isAsc: Boolean
        when (position) {
            0 -> {
                sortType = SORT_TYPE_TIME
                isAsc = false
            }
            1 -> {
                sortType = SORT_TYPE_TIME
                isAsc = true
            }
            2 -> {
                sortType = SORT_TYPE_SIZE
                isAsc = false
            }
            else -> {
                sortType = SORT_TYPE_SIZE
                isAsc = true
            }
        }
        return Pair(isAsc, sortType)
    }

    const val SORT_TYPE_SIZE = "size"
    const val SORT_TYPE_TIME = "createdAt"
    fun sortList(): Array<String> {
        return arrayOf(
            BaseApplication.sInstance.getString(R.string.sort_by_time_desc),
            BaseApplication.sInstance.getString(R.string.sort_by_time_asc),
            BaseApplication.sInstance.getString(R.string.sort_by_size_desc),
            BaseApplication.sInstance.getString(R.string.sort_by_size_asc)
        )
    }

    fun sortText(position: Int): String {
        return sortList()[position]
    }

    fun sortText(): String {
        val position = PreferencesUtils.getInt("sort_position", 0)
        return sortText(position)
    }

    val videoSuffix = arrayOf("mp4", "mpeg", "mpg", "m4v", "mov", "mkv", "webm", "ts", "avi")
    fun filterVideoBySuffix(file: File): Boolean {
        return if (file.isFile) {
            return videoSuffix.contains(file.name.substringAfter("."))
        } else {
            false
        }
    }

    val videoMimeType = arrayOf(
        "audio/x-aiff",
        "audio/mp3",
        "audio/mpeg",
        "audio/x-wav",
        "video/x-javafx",
        "video/x-flv",
        "video/x-fxm",
        "video/mp4",
        "audio/x-m4a",
        "video/x-m4v",
        "application/vnd.apple.mpegurl",
        "audio/mpegurl"
    )

    fun filterVideoByMimetype(file: DocumentFile): Boolean {
        return videoMimeType.contains(file.type)
    }

    fun hasDataUriWritePermission(): Boolean {
        return isUriWritePermission(SailfishManager.androidDataUri.toString())
    }

    fun isUriWritePermission(uriString: String): Boolean {
        val perms: List<UriPermission> = BaseApplication.sInstance.contentResolver.persistedUriPermissions
        return perms.find { it.uri.toString() == uriString && it.isWritePermission } != null
    }

    fun retrieveFile(file: File): VideoItem {
        val mmr = MediaMetadataRetriever()
        val filePath = file.absolutePath
        XLog.i(TAG, "filePath:$filePath")
        mmr.setDataSource(filePath)
        val duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLongOrNull() ?: 0
        val name = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
        val mimeType = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE)
        val width = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0
        val height = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() ?: 0
        mmr.release()
        return VideoItem(
            filePath = filePath,
            name = if (TextUtils.isEmpty(name)) FileUtils.getFileName(file) else name!!,
            dirName = dirName(file),
            mimeType = if (TextUtils.isEmpty(mimeType)) "video/mp4" else mimeType,
            size = file.length(), duration = duration,
            createdAt = file.lastModified(),
            updatedAt = System.currentTimeMillis(),
            width = width,
            height = height,
            letter = dirName(file).first().toString()
        )
    }

    fun retrieveDocumentFile(documentFile: DocumentFile): VideoItem {
        val mmr = MediaMetadataRetriever()
        mmr.setDataSource(BaseApplication.sInstance, documentFile.uri)
        val duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLongOrNull() ?: 0
        val mimeType = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE)
        val width = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0
        val height = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() ?: 0
        val name = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) ?: documentFile.name ?: ""
        mmr.release()
        return VideoItem(
            filePath = documentFile.uri.toString(),
            name = name,
            dirName = dirName(documentFile.uri.lastPathSegment ?: ""),
            mimeType = mimeType,
            size = documentFile.length(),
            duration = duration,
            createdAt = documentFile.lastModified(),
            updatedAt = System.currentTimeMillis(),
            width = width,
            height = height,
            letter = name.first().toString()
        )
    }

    private fun dirName(filePath: String): String {
        val dirList = filePath.split(File.separator)
        val size = dirList.size
        var dirName = "sdcard"
        dirName = when (size) {
            in 0..3 -> {
                "sdcard"
            }
            in 4..6 -> {
                dirList[3]
            }
            in 7..9 -> {
                dirList[5]
            }
            else -> {
                dirList[6]
            }
        }
        return dirName
    }

    private fun dirName(file: File): String {
        return dirName(file.absolutePath)
    }

    fun isAboveAndroid11(): Boolean {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
    }

    fun saveToDb(videoItem: VideoItem) {
        SailfishManager.coroutineScope.async {
            SailfishDatabase.Impl.videoDao().apply {
                add(videoItem)
                SailfishManager.addTotalSize(videoItem.size)
            }
        }
    }

    fun getFilePath(filePath: String): String {
        return if (isAboveAndroid11()) {
            //            primary:Android/data/com.ss.android.article.video/files/resources/lottie_cache/41ffc0480b5a67d4717e93dd2f135ce8/output.mp4
            Uri.parse(filePath).lastPathSegment?.replace("primary:", "/sdcard/") ?: ""
        } else {
            filePath
        }
    }
}